#include "init.h"
#include <cstdlib> // for rand()
#include <iostream>
#include<graphics.h>
#include <vector>
#include <utility>

// =================================================================
// ========== 此项是为第五部分“BOSS战策略优化”添加的代码 ==========
// =================================================================
#include <queue>      
#include <string>     
#include <algorithm>
#include <conio.h>


using namespace std;

// 假设MazeBlock和MazeMap的定义如下


inline int randomInt(int min, int max) {
	
    return rand() % (max - min + 1) + min;
}

void DivideMaze(int x1, int x2, int y1, int y2, vector<vector<MazeBlock>>& map) {
    if (x2 - x1 < 2 || y2 - y1 < 2) return;

    // 随机选择分割点（确保在有效范围内）
    int splitX = randomInt(x1 + 1, x2 - 1);
    int splitY = randomInt(y1 + 1, y2 - 1);

    for (int i = x1; i <= x2; i++) map[i][splitY].isWall = true;
    for (int j = y1; j <= y2; j++) map[splitX][j].isWall = true;

    vector<pair<int, int>> holes = {
        {randomInt(x1, splitX - 1), splitY},  // 左上区域开洞
        {randomInt(splitX + 1, x2), splitY},  // 右下区域开洞
        {splitX, randomInt(y1, splitY - 1)},  // 左下区域开洞
        {splitX, randomInt(splitY + 1, y2)}   // 右上区域开洞
    };

    // 随机选择3个洞保留（确保至少3个连通路径）
    for (int i = 0; i < 3; i++) {
        int idx = randomInt(0, holes.size() - 1);
        map[holes[idx].first][holes[idx].second].isWall = false;
        holes.erase(holes.begin() + idx);
    }
    // 递归处理四个子区域
    DivideMaze(x1, splitX - 1, y1, splitY - 1, map); // 左上
    DivideMaze(x1, splitX - 1, splitY + 1, y2, map); // 右上
    DivideMaze(splitX + 1, x2, y1, splitY - 1, map); // 左下
    DivideMaze(splitX + 1, x2, splitY + 1, y2, map); // 右下
}
void InitMaze(int size)
{
    srand(static_cast<unsigned>(time(nullptr)));  

    MazeMap maze(size);
    maze.map[0][1].isWall = false;          // 入口
    maze.start = { 0, 1 };
    maze.exit = { size - 1, size - 2 };
    DivideMaze(1, size - 2, 2, size - 3, maze.map);
    for (int i = 0; i < size; i++) {
        maze.map[i][0].isWall = true;  // 左边界
        maze.map[i][size - 1].isWall = true;  // 右边界
        maze.map[0][i].isWall = true;
        maze.map[size - 1][i].isWall = true;
    }
    DrawMaze(maze);
	WriteMazeToFile(maze, "mazemap.txt");
}

void DrawMaze(const MazeMap& maze) {
    int blockSize = 30;


    // =================================================================
// ========== 此项是为第五部分“BOSS战策略优化”添加的代码 ==========
// =================================================================
    int mazeWidth = maze.size * blockSize;


    for (int i = 0; i < maze.size; i++) {
        for (int j = 0; j < maze.size; j++) {
            if (i == maze.start.x && j == maze.start.y) {
                setfillcolor(GREEN);  // 入口用绿色
            }
            else if (i == maze.exit.x && j == maze.exit.y) {
                setfillcolor(RED);    // 出口用红色
            }
            else if (maze.map[i][j].isWall) {
                setfillcolor(BLACK);
            }
            else {
                setfillcolor(WHITE);
            }
            fillrectangle(j * blockSize, i * blockSize,
                (j + 1) * blockSize, (i + 1) * blockSize);
        }
    }
}


// =================================================================
	// ========== 此项是为第五部分“BOSS战策略优化”添加的代码 ==========
	// =================================================================
	setlinecolor(BLACK);
	rectangle(mazeWidth + 20, 20, 780, 580);
	settextcolor(BLACK);
	settextstyle(22, 0, _T("黑体"));
	outtextxy(mazeWidth + 30, 30, _T("BOSS 战报"));
	line(mazeWidth + 20, 60, 780, 60);
}


void WriteMazeToFile(const MazeMap& maze, const string& filename)
{
	ofstream file(filename);
	if (!file.is_open()) {
		cerr << "无法打开文件: " << filename << endl;
		return;
	}

	for (int i = 0; i < maze.size; i++) {
		for (int j = 0; j < maze.size; j++) {
            if (maze.start.x==i&&maze.start.y==j)
            {
                file << "S";  // 入口
            }
            else if (maze.exit.x == i && maze.exit.y == j)
            {
                file << "E";  // 入口
            }
			else if (maze.map[i][j].isWall) {
				file << "#";  // 墙
			}
			else {
				file << " ";  // 空地
			}
		}
		file << endl;
	}
	file.close();   
}



// =================================================================
// ========== 此项是为第五部分“BOSS战策略优化”添加的代码 ==========
// =================================================================

struct BattleState {
	int boss_hp;
	int rounds_elapsed;
	std::vector<int> skill_cooldowns;
	std::vector<std::string> path;
	float cost;

	bool operator>(const BattleState& other) const {
		return this->cost > other.cost;
	}
};

std::vector<std::string> solve_boss_battle_sequence(int initial_boss_hp, const std::vector<Skill>& skills) {
	float base_damage = 0;
	for (const auto& skill : skills) {
		if (skill.cooldown == 0) {
			base_damage = static_cast<float>(skill.damage);
			break;
		}
	}
	if (base_damage == 0) return {};

	auto heuristic = [&](int hp) {
		return (hp > 0) ? (hp / base_damage) : 0.0f;
	};

	std::priority_queue<BattleState, std::vector<BattleState>, std::greater<BattleState>> pq;

	BattleState initial_state;
	initial_state.boss_hp = initial_boss_hp;
	initial_state.rounds_elapsed = 0;
	initial_state.skill_cooldowns.assign(skills.size(), 0);
	initial_state.cost = heuristic(initial_state.boss_hp);
	pq.push(initial_state);

	int min_rounds_found = 1000;
	std::vector<std::string> best_path;

	while (!pq.empty()) {
		BattleState current_state = pq.top();
		pq.pop();

		if (current_state.cost >= min_rounds_found) continue;

		for (size_t i = 0; i < skills.size(); ++i) {
			if (current_state.skill_cooldowns[i] == 0) {
				BattleState next_state;
				next_state.rounds_elapsed = current_state.rounds_elapsed + 1;
				next_state.boss_hp = current_state.boss_hp - skills[i].damage;
				next_state.path = current_state.path;
				next_state.path.push_back(skills[i].name);

				next_state.skill_cooldowns = current_state.skill_cooldowns;
				for (size_t j = 0; j < next_state.skill_cooldowns.size(); ++j) {
					next_state.skill_cooldowns[j] = std::max(0, next_state.skill_cooldowns[j] - 1);
				}
				next_state.skill_cooldowns[i] = skills[i].cooldown;

				if (next_state.boss_hp <= 0) {
					if (next_state.rounds_elapsed < min_rounds_found) {
						min_rounds_found = next_state.rounds_elapsed;
						best_path = next_state.path;
					}
				}
				else {
					float g_n = static_cast<float>(next_state.rounds_elapsed);
					float h_n = heuristic(next_state.boss_hp);
					next_state.cost = g_n + h_n;
					if (next_state.cost < min_rounds_found) {
						pq.push(next_state);
					}
				}
			}
		}
	}
	return best_path;
}

void display_battle_on_screen(
	const std::vector<std::string>& sequence,
	const std::vector<Skill>& skills,
	Player& player,
	Boss& boss
) {
	int logX = 470;
	int logY = 80;
	int lineHeight = 25;
	char buffer[100];

	settextcolor(BLACK);
	setbkmode(TRANSPARENT);

	settextstyle(16, 0, _T("微软雅黑"));
	sprintf_s(buffer, "玩家初始血量: %d", player.hp);
	outtextxy(logX, logY, buffer);
	sprintf_s(buffer, "BOSS初始血量: %d", boss.bossHp);
	outtextxy(logX, logY + lineHeight, buffer);

	Sleep(1000);

	for (size_t i = 0; i < sequence.size(); ++i) {
		clearrectangle(logX - 1, logY + lineHeight * 2, 779, 579);

		settextstyle(18, 0, _T("黑体"));
		sprintf_s(buffer, "------ 第 %d 回合 ------", i + 1);
		outtextxy(logX, logY + lineHeight * 2, buffer);

		const string& skill_name = sequence[i];
		int player_damage = 0;
		for (const auto& s : skills) {
			if (s.name == skill_name) {
				player_damage = s.damage;
				break;
			}
		}
		boss.bossHp -= player_damage;

		settextstyle(16, 0, _T("宋体"));
		string player_action_str = "玩家 使用 [" + skill_name + "]";
		outtextxy(logX, logY + lineHeight * 3, player_action_str.c_str());
		sprintf_s(buffer, "对BOSS造成 %d 点伤害。", player_damage);
		outtextxy(logX, logY + lineHeight * 4, buffer);

		player.hp -= boss.bossAtk;
		sprintf_s(buffer, "BOSS反击, 对玩家造成 %d 点伤害。", boss.bossAtk);
		outtextxy(logX, logY + lineHeight * 5, buffer);

		settextcolor(BLUE);
		sprintf_s(buffer, "玩家剩余血量: %d", player.hp > 0 ? player.hp : 0);
		outtextxy(logX, logY + lineHeight * 7, buffer);
		settextcolor(RED);
		sprintf_s(buffer, "BOSS剩余血量: %d", boss.bossHp > 0 ? boss.bossHp : 0);
		outtextxy(logX, logY + lineHeight * 8, buffer);
		settextcolor(BLACK);

		if (!player.isAlive()) {
			settextstyle(24, 0, _T("隶书"));
			settextcolor(DARKGRAY);
			outtextxy(logX, logY + lineHeight * 11, "玩家战败...");
			return;
		}
		if (boss.bossHp <= 0) {
			settextstyle(24, 0, _T("隶书"));
			settextcolor(0x008000);
			outtextxy(logX, logY + lineHeight * 11, "BOSS已被击败!");
			return;
		}

		Sleep(1500);
	}
}

void plan_and_execute_boss_battle() {
	std::vector<Skill> player_skills = {
		{"普通攻击", 5, 0},
		{"大招", 10, 2}
	};

	Player player({ 0,0 });
	Boss boss({ 0,0 });

	std::vector<std::string> optimal_sequence = solve_boss_battle_sequence(boss.bossHp, player_skills);

	if (!optimal_sequence.empty()) {
		display_battle_on_screen(optimal_sequence, player_skills, player, boss);
	}
	else {
		settextcolor(RED);
		settextstyle(16, 0, _T("微软雅黑"));
		outtextxy(470, 80, "未找到能击败BOSS的策略!");
	}
}